package api

import (
	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/httpmvc/api"
	"gitee.com/sansaniot/ssiot-core/serrors"
	"github.com/gin-gonic/gin"
	"ssdevice/common/constant"
	"ssdevice/common/cron"
	"ssdevice/internal/rule/engine"
	"ssdevice/internal/rule/model"
	"ssdevice/internal/rule/model/command"
	"ssdevice/internal/rule/model/query"
)

type Processor struct {
	api.Api
}

// FindList 获取处理器信息列表
func (s Processor) FindList(c *gin.Context) {
	// 请求参数
	req := &query.ProcessorGetReq{}
	//	模型
	m := &model.Processor{}
	// 上下文
	err := s.MakeContext(c).Bind(req).MakeModel(&m.Model).Errors
	if err != nil {
		s.Logger.Error(err)
		s.Fail(serrors.InvalidParam)
		return
	}

	//	执行
	result, count, err1 := m.FindPage(req)
	if err1 != nil {
		s.Logger.Error(err)
		s.Fail(0, err.Error())
		return
	}
	// 返回
	s.Page(count, req.GetPageSize(), req.GetPageIndex(), result)
}

// Get 获取处理器信息
func (s Processor) Get(c *gin.Context) {
	// 请求参数
	req := &query.ProcessorGetReq{}
	// 模型
	m := &model.Processor{}
	// 上下文
	err := s.MakeContext(c).Bind(req).MakeModel(&m.Model).Errors
	if err != nil {
		s.Logger.Error(err)
		s.Fail(serrors.InvalidParam)
		return
	}

	// 执行
	if err = m.GetOne(req); err != nil {
		s.Logger.Error(err)
		s.Fail(serrors.SelectFail)
		return
	}
	// 返回
	s.Data(m)
}

// Create 创建处理器
func (s Processor) Create(c *gin.Context) {
	req := &command.ProcessorInsertReq{}
	m := &model.Processor{}
	err := s.MakeContext(c).Bind(req).MakeModel(&m.Model).Errors
	if err != nil {
		s.Logger.Error(err)
		s.Fail(serrors.InvalidParam)
		return
	}

	// model赋值
	_ = req.Generate(m)
	s.enabledTask(m.Id)

	// 添加规则
	if err = m.AddProcessor(); err != nil {
		s.Logger.Error(err)
		s.Fail(serrors.InsertFail)
		return
	}

	s.Ok(m.Id)
}

// Modify 更新处理器
func (s Processor) Modify(c *gin.Context) {
	req := &command.ProcessorUpdateReq{}
	m := &model.Processor{}

	err := s.MakeContext(c).Bind(req).MakeModel(&m.Model).Errors
	if err != nil {
		s.Logger.Error(err)
		s.Fail(serrors.InvalidParam)
		return
	}

	_ = req.Generate(m)
	if req.Trigger != constant.RuleTriggerSchedule {
		s.disableTask(m.Id)
	} else {
		s.enabledTask(m.Id)
	}

	err = m.Modify(m)
	if err != nil {
		s.Logger.Error(err)
		s.Fail(serrors.ModifyFail)
		return
	}

	s.Ok(m.Id)
}

// Remove 删除处理器
func (s Processor) Remove(c *gin.Context) {
	req := &command.ProcessorOperReq{}
	m := &model.Processor{}

	err := s.MakeContext(c).Bind(req).MakeModel(&m.Model).Errors
	if err != nil {
		s.Logger.Error(err)
		s.Fail(serrors.InvalidParam)
		return
	}

	s.disableTask(req.Id)
	m.Id = req.Id
	err = m.Remove()
	if err != nil {
		s.Logger.Error(err)
		s.Fail(serrors.DeleteFail)
		return
	}

	s.Ok(m.Id)
}

func (s Processor) enabledTask(processorId string) {
	processor := &model.Processor{}
	rule := &model.Rule{}
	rule.Orm = env.Db
	processor.Orm = env.Db
	_ = processor.GetById(processorId)
	_ = rule.GetById(processor.RuleId)

	if rule.Status == constant.RuleEnable && processor.Trigger == constant.RuleTriggerSchedule {
		sns := getStatSns(processor.RuleId)
		// 先停用再启用
		cron.RemoveTask(processor.ScheduleId)
		scheduleId := cron.AddCronTask(processor.Schedule, func() { engine.ExecScheduleTask(processor, sns) }, false)

		_ = processor.SaveScheduleId(int(scheduleId))
		env.Log.Infof("add processor %s with schedule id %d (%s) for %d devices", processor.Id, scheduleId, processor.Schedule, len(sns))
	}
}

func (s Processor) disableTask(processorId string) {
	processor := &model.Processor{}
	rule := &model.Rule{}
	rule.Orm = env.Db
	processor.Orm = env.Db
	_ = processor.GetById(processorId)
	_ = rule.GetById(processor.RuleId)

	if rule.Status == constant.RuleEnable && processor.Trigger == constant.RuleTriggerSchedule {
		cron.RemoveTask(processor.ScheduleId)
		_ = processor.SaveScheduleId(0)

		env.Log.Infof("remove processor %s with schedule id %d (%s)", processor.Id, processor.ScheduleId, processor.Schedule)
	}
}
